package org.traditionalcake.probablecalls.agitemplates;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.traditionalcake.probablecalls.AgiActionName;
import org.traditionalcake.probablecalls.AgiEntryPoint;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.inject.Container;

public class AgiTemplateDispatcher implements Result {

    private static final long serialVersionUID = 1L;

    private List<AgiTemplateSource> _sources = new ArrayList<AgiTemplateSource>();

    /**
     * xwork reads this field to determine which property to set with the result
     * body
     */
    public static final String DEFAULT_PARAM = "target";

    private boolean _hasInitialized = false;

    private String _target;

    private Map<String, Class<?>> _templates = new HashMap<String, Class<?>>();

    public void setTarget(String target) {
        _target = target;
    }

    public void setTemplateSource(AgiTemplateSource source) {
        _sources.add(source);
    }

    public void setTemplateSources(Collection<AgiTemplateSource> sources) {
        _sources.addAll(sources);
    }

    public void execute(ActionInvocation action) throws Exception {

        init();

        Class<?> c = _templates.get(_target);

        if (c == null) {
            System.err.println("no such template: " + _target);
            return;
        }

        ActionContext context = action.getInvocationContext();

        Container container = context.getContainer();
        ObjectFactory factory = container.getInstance(ObjectFactory.class);
        AgiTemplate template = (AgiTemplate) factory.buildBean(c, context.getContextMap());

        AgiActionName nextAction = template.execute(context);
        if (nextAction != null)
            AgiEntryPoint.setNextAction(context, nextAction);
    }

    private void init() throws IOException {

        if (_hasInitialized)
            return;

        _hasInitialized = true;

        for (AgiTemplateSource source : _sources) {
            Map<String, Class<?>> templates = source.getTemplates();
            _templates.putAll(templates);
        }
    }
}
